package org.jaaksi.router

import com.android.build.api.transform.*
import com.android.build.gradle.internal.pipeline.TransformManager
import org.apache.commons.codec.digest.DigestUtils
import org.apache.commons.io.FileUtils
import org.gradle.api.Project

class RouterTransform extends Transform {
  static File registerTargetFile = null

  Project project

  /**
   * 构造函数，我们将Project保存下来备用
   * @param project
   */
  RouterTransform(Project project) {
    this.project = project
  }

  /**
   * transform的名称
   * Task :app:transformClassesWithRouterForDebug 运行时的名字
   * transformClassesWith + getName() + For + Debug或Release
   * @return
   */
  @Override
  String getName() {
    return "router"
  }

  /**
   * 指定输入的类型，通过这里的设定，可以指定我们要处理的文件类型
   * 需要处理的数据类型，有两种枚举类型
   * CLASSES和RESOURCES，CLASSES代表处理的java的class文件，RESOURCES代表要处理java的资源
   * 这样确保其他类型的文件不会传入
   * @return
   */
  @Override
  Set<QualifiedContent.ContentType> getInputTypes() {
    return TransformManager.CONTENT_CLASS
  }

  /**
   * 指Transform要操作内容的范围，官方文档Scope有7种类型：
   //
   //    EXTERNAL_LIBRARIES        只有外部库
   //    PROJECT                       只有项目内容
   //    PROJECT_LOCAL_DEPS            只有项目的本地依赖(本地jar)
   //    PROVIDED_ONLY                 只提供本地或远程依赖项
   //    SUB_PROJECTS              只有子项目。
   //    SUB_PROJECTS_LOCAL_DEPS   只有子项目的本地依赖项(本地jar)。
   //    TESTED_CODE                   由当前变量(包括依赖项)测试的代码
   * @return
   */
  @Override
  Set<? super QualifiedContent.Scope> getScopes() {
    return TransformManager.SCOPE_FULL_PROJECT
  }

  /**
   * 指明当前Transform是否支持增量编译
   * @return
   */
  @Override
  boolean isIncremental() {
    return false
  }

  @Override
  void transform(Context context,
      Collection<TransformInput> inputs,
      Collection<TransformInput> referencedInputs,
      TransformOutputProvider outputProvider,
      boolean isIncremental)
      throws IOException, TransformException, InterruptedException {
  }

  /**
   *  Transform中的核心方法，
   *  inputs中是传过来的输入流，其中有两种格式，一种是jar包格式一种是目录格式。
   *  outputProvider 获取到输出目录，最后将修改的文件复制到输出目录，这一步必须做不然编译会报错
   * @param transformInvocation
   * @throws TransformException* @throws InterruptedException* @throws IOException
   */
  @Override
  void transform(TransformInvocation transformInvocation)
      throws TransformException, InterruptedException, IOException {
    long begin = System.currentTimeMillis()
    // logger日志怎么看啊？
    println("========================router transform begin==========================")

    transformInvocation.inputs.each { TransformInput input ->
      // 遍历所有的jar
      if (!input.jarInputs.empty) {
        println(">>> jarInputs")
        input.jarInputs.each { JarInput jarInput ->
          // com.android.support:appcompat-v7:28.0.0(/Users/yang/.gradle/caches/transforms-1/files-1.1/appcompat-v7-28.0.0.aar/c962891bd62dda26f4c11fe603261c26/jars/classes.jar)
          // 本地依赖的jar包
          // android.local.jars:zxing.jar:9ef852c7a923894b8ee248314eb3f4e5807367b7(/Users/yang/GitRespositories/github/GradlePluginDemo/app/libs/zxing.jar)

          println("========================jarInputs==========================")
          println("${jarInput.name}(${jarInput.file.absolutePath})")

          String destName = jarInput.name
          String hexName = DigestUtils.md5Hex(jarInput.file.absolutePath)
          if (destName.endsWith(".jar")) {
            // local jar
            // rename to avoid the same name, such as classes.jar
            destName = "${destName.substring(0, destName.length() - 4)}_${hexName}"
          }
          // 获取output目录
          File destFile = transformInvocation.outputProvider.getContentLocation(
              destName, jarInput.contentTypes, jarInput.scopes, Format.JAR)

          // fixme 扫描指定的jar ：org.jaaksi:pickerview:2.0.0（gradle依赖，jarInput.name就是依赖的name）
          if (jarInput.name.startsWith("org.jaaksi:pickerview")) {
            println("======= 扫描pickerview jar========")
            Scanner.scanJar(jarInput.file, destFile)
          }
//          if (Scanner.shouldScanJar(jarInput)) {
//            println(
//                "========================scan Jar`s class($jarInput.name) ==========================")
//
//            Scanner.scanJar(jarInput.file, destFile)
//          }

          FileUtils.copyFile(jarInput.file, destFile)
        }
      }

      // 遍历所有的目录
      if (!input.directoryInputs.empty) {
        println(">>> directoryInputs")
        input.directoryInputs.each { DirectoryInput directoryInput ->
          println("========================directoryInputs==========================")
          println("${directoryInput.name} (${directoryInput.file.absolutePath})")
          File dest = transformInvocation.outputProvider.getContentLocation(
              directoryInput.name, directoryInput.contentTypes, directoryInput.scopes,
              Format.DIRECTORY)
          println("-- dest dir: ${dest.absolutePath}")
          directoryInput.file.eachFileRecurse { File file ->
            if (file.isFile() && Scanner.shouldScanClass(file)) {
              println("--- ${file.absolutePath}")
              Scanner.scanClass(file)
            }
          }

          FileUtils.copyDirectory(directoryInput.file, dest)
        }
      }
    }

    // 找到了AptHub.class 向其注入代码
    //    if (registerTargetFile) {
    //      println("begin to register code to ${registerTargetFile.absolutePath}")
    //      Knife.handle()
    //    } else {
    //      project.logger.warn("router: register target file not found.")
    //    }
    println("- router transform finish.")
    println("cost time: ${(System.currentTimeMillis() - begin) / 1000.0f}s")
  }
}
